package com.tbit.main.pojo.maintain_performance;

import com.tbit.main.constant.enums.ConditionLogic;
import com.tbit.main.constant.enums.RuleLogic;
import com.tbit.main.pojo.PerformanceRuleCondition;
import lombok.Data;

import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 表示范围的通用包装类
 *
 * @author <a href="mailto:zheng.zebiao@tbit.com.cn">zb</a>
 * @since 2025/2/18
 */
@Data
public class Range<T extends Comparable<T>> {
    /**
     * 开始
     */
    private T start;
    /**
     * 结束（不含）
     */
    private T end;

    public T getStart() {
        if (start instanceof String){
            if (((String) start).contains(":")){
                String s = ((String) start).split(":")[0];
                if (s.length() == 1){
                    start = (T) ("0" + start);
                }
            }
        }
        return start;
    }

    public T getEnd() {
        if (end instanceof String){
            if (((String) end).contains(":")){
                String s = ((String) end).split(":")[0];
                if (s.length() == 1){
                    end = (T) ("0" + end);
                }
            }
        }
        return end;
    }

    public T getStart2Calc() {
        if (start instanceof String){
            if (((String) start).contains(":")){
                String s = ((String) start).split(":")[0];
                if (s.length() == 1){
                    return (T) ("0" + start);
                }
                if (s.length() == 2 && "24".equals(s)){
                    return (T) "23:59:59";
                }
            }
        }
        return start;
    }

    public T getEnd2Calc() {
        if (end instanceof String){
            if (((String) end).contains(":")){
                String s = ((String) end).split(":")[0];
                if (s.length() == 1){
                    return (T) ("0" + end);
                }
                if (s.length() == 2 && "24".equals(s)){
                    return (T) "23:59:59";
                }
            }
        }
        return end;
    }

    public PerformanceRuleCondition toCondition(String key) {
        PerformanceRuleCondition condition = new PerformanceRuleCondition();
        condition.setKey(key);
        condition.setLogic(RuleLogic.BETWEEN);
        condition.setValue(toString());
        return condition;
    }

    @Override
    public String toString() {
        if (start == null) {
            return String.format("<%s", end);
        }
        if (end == null) {
            return String.format("≥%s", start);
        }
        return String.format("%s~%s", start, end);
    }

    /**
     * 从DB对象解析范围对象
     */
    public static <T extends Comparable<T>> Range<T> from(PerformanceRuleCondition condition, Function<String, T> parser) {
        return parse(condition.getValue(), parser);
    }

    /**
     * 从字符串解析范围对象
     */
    public static <T extends Comparable<T>> Range<T> parse(String value, Function<String, T> parser) {
        Range<T> range = new Range<>();
        if (value.contains("~")) {
            String[] pair = value.split("~");
            range.setStart(parser.apply(pair[0]));
            range.setEnd(parser.apply(pair[1]));
        } else if (value.startsWith("<")) {
            range.setEnd(parser.apply(value.substring(1)));
        } else if (value.startsWith("≥")) {
            range.setStart(parser.apply(value.substring(1)));
        } else throw new IllegalArgumentException("无效范围值: " + value);
        return range;
    }

    /**
     * 组合多个范围条件，转为单个DB对象
     */
    public static <T extends Comparable<T>> PerformanceRuleCondition combine(String key, List<Range<T>> pairs, ConditionLogic logic) {
        PerformanceRuleCondition condition = new PerformanceRuleCondition();
        condition.setKey(key);
        condition.setLogic(logic == ConditionLogic.AND ? RuleLogic.SUB_BETWEEN_AND : RuleLogic.SUB_BETWEEN_OR);
        condition.setValue(pairs.stream()
                .map(Range::toString)
                .collect(Collectors.joining(",")));
        return condition;
    }

    /**
     * 从DB对象解析组合条件，转为多个范围对象
     */
    public static <T extends Comparable<T>> List<Range<T>> unCombine(PerformanceRuleCondition condition, Function<String, T> parser) {
        List<Range<T>> pairs = new ArrayList<>();
        String[] values = condition.getValue().split(",");
        for (String value : values) {
            pairs.add(parse(value, parser));
        }
        return pairs;
    }

    /**
     * 判断值是否在范围内，按左闭右开原则匹配
     */
    public boolean match(T value) {
        if (value == null) {
            return false;
        }
        if (start == null) {
            if (value instanceof Integer && (Integer) end == 100) {
                return value.compareTo(end) <= 0;
            }
            return value.compareTo(end) < 0;
        }
        if (end == null) {
            return value.compareTo(start) > -1;
        }

        // 时间类型存在时间循环，如23:00和3:00都在21:00-05:00区间内，需要特殊处理
        if (value instanceof LocalTime) {
            if (start.compareTo(end) > 0) {
                return value.compareTo(start) > -1 || value.compareTo(end) < 0;
            }
        }
        if (value instanceof Integer && (Integer) end == 100) {
            return value.compareTo(start) > -1 && value.compareTo(end) <= 0;
        }
        return value.compareTo(start) > -1 && value.compareTo(end) < 0;
    }

    /**
     * 判断值是否在范围内，按左闭右闭原则匹配
     */
    public boolean matchAllClosed(T value) {
        if (value == null) {
            return false;
        }
        if (start == null) {
            return value.compareTo(end) <= 0;
        }
        if (end == null) {
            return value.compareTo(start) >= 0;
        }

        // 时间类型存在时间循环，如23:00和3:00都在21:00-05:00区间内，需要特殊处理
        if (value instanceof LocalTime) {
            if (start.compareTo(end) > 0) {
                return value.compareTo(start) >= 0 || value.compareTo(end) <= 0;
            }
        }
        return value.compareTo(start) >= 0 && value.compareTo(end) <= 0;
    }

    public static void main(String[] args) {
        Range<Integer> range = new Range<>();
        range.setEnd(100);
        System.out.println(range.match(100));
    }
}
